#include <boost/numeric/conversion/cast.hpp>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <string>
#include <fstream>
#include <iostream>
#include <stdio.h>
//
//#include <OgreTagPoint.h>
//#include <OgreBone.h>
#include <Ogre.h>

#include "InputManager.h"
// Lua
#include <tolua++.h>
#include <lua.hpp>
#include <lualib.h>
#include <lauxlib.h>
#include "tolua_Vector3.h"
// CEGUI includes
#include "CEGUISystem.h"
#include "CEGUIInputEvent.h"
#include "CEGUIWindow.h"
#include "CEGUIWindowManager.h"
#include "CEGUISchemeManager.h"
#include "CEGUIFontManager.h"
#include <elements/CEGUIPushButton.h>
#include "elements/CEGUIFrameWindow.h"

// system includes
#include "UIEngine.h"
#include "UI.h"
#include "Defs.h"
//-------------------------------------------------------------------------------------
using namespace Ogre;
using namespace boost;
namespace fs = boost::filesystem;

CUIEngine::CUIEngine()
: ogreHead(0),
headNode(0)
{
    // Set default values for variables
    mFolder = "D:/projects/greendam";
    //std::filebuf *f = new std::filebuf;
    //f->open("cout.txt", std::ios::out);
    //std::streambuf* buf = std::cout.rdbuf();
    //std::cout.rdbuf(f);
    //std::cout << "Hello File!" <<std::endl;
}
//-------------------------------------------------------------------------------------
CUIEngine::~CUIEngine()
{
}
//-------------------------------------------------------------------------------------
void CUIEngine::addResourceLocations() {
    CEngine::addResourceLocations();
    
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        (fs::path(mFolder)/"resource").string(), "FileSystem", "Magica");
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        (fs::path(mFolder)/"resource/image").string(), "FileSystem", "Magica");

    //===========================================================
    // CEGUI
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        (fs::path(mFolder)/"resource/gui").string(), "FileSystem", "GUI");
#if defined(WIN32)
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "c:\\windows\\fonts", "FileSystem", "GUI");
#endif

}
//-------------------------------------------------------------------------------------
bool CUIEngine::processUnbufferedKeyInput(const Ogre::FrameEvent& evt)
{
    using namespace Ogre;
    using namespace OIS;
    OIS::Keyboard *mInputDevice = CInputManager::getSingletonPtr()->getKeyboard();

    if( mInputDevice->isKeyDown( KC_ESCAPE) )
    {
        return false;
    }

    return true;
}
//-------------------------------------------------------------------------------------
bool CUIEngine::processUnbufferedMouseInput(const Ogre::FrameEvent& evt)
{
    using namespace Ogre;
    using namespace OIS;

    return true;
}
void CUIEngine::initLua() {
    mLua = lua_open();
    luaL_openlibs(mLua);   // initalize all lua standard library functions
    tolua_open(mLua);          // initalize tolua
    tolua_Vector3_open(mLua);

}
void CUIEngine::destroyLua() {
    lua_close(mLua);
}
bool CUIEngine::test(const CEGUI::EventArgs& ) {
    GAME_LOG("click_test");
    return true;
}
//-------------------------------------------------------------------------------------
void CUIEngine::createScene()
{
    // ogre test
    // test object
    using namespace Ogre;
	ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");

	headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	headNode->attachObject(ogreHead);
    headNode->setVisible(true);
	// Set ambient light
	mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

	// Create a light
	Light* l = mSceneMgr->createLight("MainLight");
	l->setPosition(20,80,50);


    //// Set the camera to look at our handiwork
    mCamera->setPosition(0, 0,1000);
    mCamera->lookAt(Vector3(0,0,0));
    mCamera->setNearClipDistance(0.1f);
   
    //===========================================================
    // lua init and test
    initLua();
    lua_State *L = lua();

    std::cout << "LogTest" << std::endl;
    if (luaL_dostring(lua(), "vec3 = Ogre.Vector3:new(); vec3.x = 0; vec3.y = 1; vec3.z = 0; \
                             io.stdout:write(\"vector3(\"..vec3.x..\", \"..vec3.y..\", \"..vec3.z..\")\\n\");")) {
                                 //lua_error(L);

        Ogre::LogManager::getSingletonPtr()->logMessage(lua_tostring(lua(), -1));
        lua_pop(lua(), 1); // remove error message
    }
    lua_getglobal(lua(), "vec3");
    Vector3 *vec3 = (Vector3*)tolua_tousertype(lua(), -1, 0);
    //==============================================================================
    // gui test

    if (UI::getSingletonPtr() == NULL) {
        new UI;
    }
    UI::getSingletonPtr()->init(mWindow);
    mInputMgr->addMouseListener(UI::getSingletonPtr(), "CEGUI");
    mInputMgr->addKeyListener(UI::getSingletonPtr(), "CEGUI");

    using namespace CEGUI;
    CEGUI::Window *myImageWindow = CEGUI::WindowManager::getSingleton().
        createWindow("TaharezLook/StaticImage","PrettyWindow" );
    myImageWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.5,0),CEGUI::UDim(0.5,0)));
    myImageWindow->setSize(UVector2(UDim(0,150),UDim(0,100)));
    myImageWindow->setProperty("Image","set:TaharezLook image:full_image");
    CEGUI::System::getSingletonPtr()->getGUISheet()->addChildWindow(myImageWindow);

    CEGUI::Window * gJumpBtnWindow = CEGUI::WindowManager::getSingleton().
        createWindow("TaharezLook/Button","JumpPushButton");  // Create Window
    gJumpBtnWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.75,0),CEGUI::UDim(0.50,0)));
    gJumpBtnWindow->setSize(CEGUI::UVector2(CEGUI::UDim(0,50),CEGUI::UDim(0,50)));
    gJumpBtnWindow->setText("Jump!");
    CEGUI::System::getSingleton().getGUISheet()->addChildWindow(gJumpBtnWindow);  

    gJumpBtnWindow->subscribeEvent(CEGUI::PushButton::EventClicked,
        CEGUI::Event::Subscriber(&CUIEngine::test, this));
    
    CEGUI::Window *newWindow = CEGUI::WindowManager::getSingleton().loadWindowLayout("test.layout");
    CEGUI::System::getSingleton().getGUISheet()->addChildWindow(newWindow);
    
}

void CUIEngine::destroyScene() {
    destroyLua();
}

//-------------------------------------------------------------------------------------
void CUIEngine::animate(int time) {

}

//-------------------------------------------------------------------------------------
bool CUIEngine::frameStarted(const FrameEvent& evt)
{
	// Just a silly example to demonstrate how much easier this is than passing objects to an external framelistener
	headNode->translate(0.0f, 0.000f, 0.0f);

    //------------------------------------------------------------------------------
 	return CEngine::frameStarted(evt);
}


